#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <dirent.h>
#include <sys/stat.h>
#include <pwd.h>
#include <grp.h>
#include <string.h>
#include "headers/result.h"
#include "headers/scandir.h"

int userExist(char *usr)
{
	struct passwd *user;
	user = (struct passwd *) getpwnam(usr);
	return (user != NULL);	
}

int groupExist(char *grp)
{
	struct group *groupe;
	groupe = (struct group *) getgrnam(grp);
 	return (groupe != NULL);
}

/* Vérifie l'appartenance du fichier à l'utilisateur */
int compareUID(int uid, char *userName)
{
	struct passwd *user;
	user = (struct passwd *) getpwnam(userName);
	return uid == user->pw_uid; // Comparaison de l'UID
}

/* Vérifie l'appartenance du fichier au groupe */
int compareGID(int gid, char *groupName)
{
	struct group *grp;
	grp = (struct group *) getgrnam(groupName);
	return gid == grp->gr_gid; // Comparaison du GID
}

/* Vérifie l'appartenance du fichier à un des utilisateurs du groupe */
int compareUIDinGroup(int uid, char *groupName)
{
	int i=0;
	struct group *grp;
	grp = (struct group *) getgrnam(groupName);
	
	while(grp->gr_mem[i] != NULL) 
	{
		if(compareUID(uid, grp->gr_mem[i]))
			return 1;
		i++;
	}
	
	return 0;
}

/* Parcours toute l'arborescence de path en renseignant la structure resultat */
void scanDir(Resultat *resultat, char *path, char **users, char **groups, char **groups2, int nbUsers, int nbGroups, int nbGroups2)
{
	int i = 0;
	int fichierTrouve = 0;
	
	DIR *in;
	struct dirent *rep;

	in = opendir(path);

	if(in == NULL) { perror("Erreur scanDir() "); exit(1); }

	while((rep = readdir(in)))
	{
		if(strcmp(rep->d_name,".") && strcmp(rep->d_name,"..")) {
			char *fullPath;
			fullPath = (char *) malloc((strlen(path)+strlen(rep->d_name)+2) * sizeof(char));				
			sprintf(fullPath, "%s/%s", path, rep->d_name); // Concaténation du repertoire courant avec celui de l'appel précédent
			
			// Structure stats pour lire des informations du fichier
			struct stat stats;
			if(lstat(fullPath, &stats) != 0) { perror("Erreur lstat "); exit(1); }
			
			if(S_ISDIR(stats.st_mode)) // Si c'est un répertoire, on le parcours -> appel récursif
				scanDir(&(*resultat), fullPath, users, groups, groups2, nbUsers, nbGroups, nbGroups2);
			else if(S_ISREG(stats.st_mode)) { // Si ce ne pas un lien symbolique -> est un fichier régulier et n'est pas un répertoire (S_ISLNK ne fonctionnant pas)
				
				for(i=0; i<nbUsers; i++) // On regarde si le fichier appartient à un des utilisateurs
				{
					if(compareUID(stats.st_uid, users[i])) {
						(*resultat)->infoTotal->totalsize += stats.st_size;
						(*resultat)->infoTotal->nbfiles++;
						(*resultat)->infoUser[i]->totalsize += stats.st_size;
						(*resultat)->infoUser[i]->nbfiles++;
						fichierTrouve = 1;
						break;
					}
				}

				for(i=0; i<nbGroups; i++) // On regarde si le fichier appartient à un des groupes
				{
					if(compareGID(stats.st_gid, groups[i])) {
						if(!fichierTrouve) { // Si le fichier n'a pas déjà été trouvé, on l'ajoute au total
							(*resultat)->infoTotal->totalsize += stats.st_size;
							(*resultat)->infoTotal->nbfiles++;
						}
						(*resultat)->infoGroup[i]->totalsize += stats.st_size;
						(*resultat)->infoGroup[i]->nbfiles++;
						fichierTrouve = 1;
						break;
					}
				}
				
				for(i=0; i<nbGroups2; i++)
				{
					if(compareUIDinGroup(stats.st_uid, groups2[i])) {
						if(!fichierTrouve) { // Si le fichier n'a pas déjà été trouvé, on l'ajoute au total
						//	printf("file : %s\n",fullPath);
							(*resultat)->infoTotal->totalsize += stats.st_size;
							(*resultat)->infoTotal->nbfiles++;
						}
						(*resultat)->infoGroup2[i]->totalsize += stats.st_size;
						(*resultat)->infoGroup2[i]->nbfiles++;
						break;
					}
				}
				fichierTrouve = 0;
			}
		}	
	}
	closedir(in);
}
